/**
Structs used in simulation
**/

#include "Structs.h"

using namespace std;

SubStream::SubStream(int id, int sID, int pID, string addr, int r) {
	ID = id;
	streamID = sID;
	peerID = pID;
	peerAddr = addr;
	rank = r;
	nextChunk = 0;
	timestamp = 0;
	online = true;
}

void SubStream::changePeer (int pID, string addr) {
	peerID = pID;
	peerAddr = addr;
}

int SubStream::getSubStreamID() {
	return ID;
}

int SubStream::getPeerID() {
	return peerID;
}

string SubStream::getPeerAddr() {
	return peerAddr;
}

int SubStream::getStreamID() {
	return streamID;
}

int SubStream::getNextChunk() {
	return nextChunk;
}

int SubStream::getRank() {
	return rank;
}

double SubStream::getTimestamp() {
	return timestamp;
}

void SubStream::setTimestamp(double t) {
	timestamp = t;
}

bool SubStream::compareTo(int ID_, int streamID_, int peerID_) {
	if (peerID_ != peerID)
		return false;
	
	if (streamID_ != streamID)
		return false;
	
	if ( (ID_ != MAX_SUBSTREAM) and (ID_ != ID) )
		return false;

	return true;
}

bool SubStream::isOnline () {
	return online;
}


void SubStream::setOffline () {
	online=false;
}

void SubStream::update () {
	nextChunk++;
	if (!online)
		online=true;

}

TrackerTable::TrackerTable() {
}

bool TrackerTable::searchEntry(unsigned peer, unsigned stream) {
	for (unsigned i = 0; i < entries.size(); i++)
		if ( (entries[i].peerID == peer) and (entries[i].streamID == stream) )
			return true;
	
	return false;
}

bool TrackerTable::searchEntry(string addr, unsigned stream) {
	for (unsigned i = 0; i < entries.size(); i++)
		if ( (entries[i].addr == addr) and (entries[i].streamID == stream) )
			return true;
	
	return false;
}

vector<unsigned> TrackerTable::getPeersIDs(unsigned stream) {
	vector<unsigned> v;
	for (unsigned i = 0; i < entries.size(); i++)
		if ( entries[i].streamID == stream )
			v.push_back(entries[i].peerID);
	
	return v;
}

vector<string> TrackerTable::getPeersAddrs(unsigned stream) {
	vector<string> v;
	for (unsigned i = 0; i < entries.size(); i++)
		if ( entries[i].streamID == stream )
			v.push_back(entries[i].addr);
	
	return v;
}


void TrackerTable::removePeer(unsigned peer) {
	unsigned i = 0;
	while (i < entries.size())
		if (entries[i].peerID == peer)
			entries.erase(entries.begin()+i);
		else
			i++;
	
	return;
}

void TrackerTable::removePeerAddr(string addr) {
	unsigned i = 0;
	while (i < entries.size())
		if (entries[i].addr == addr)
			entries.erase(entries.begin()+i);
		else
			i++;
	
	return;
}

unsigned TrackerTable::insertEntry(unsigned peer, unsigned stream, string addr) {
	streamTrack t;
	t.peerID = peer;
	t.streamID = stream;
	t.addr = addr;
	
	if (!searchEntry(peer,stream))
		entries.push_back(t);
	
	return entries.size();
}

Candidate::Candidate(string addr, double r=0.0, double d=0) {
	address = addr;
	rtt = r;
	distance = d;
	used = false;
}

std::string Candidate:: getAddress() const{
	return address;
}
double Candidate::getRtt() const{
	return rtt;
}

double Candidate::getDistance() const{
	return distance;
}
	
void Candidate::setDistance(double d) {
	distance = d;
}

void Candidate::setRtt(double r) {
	rtt = r;
}
	
bool Candidate::isUsed() {
	return used;
}	
	
void Candidate::setUse(bool u) {
	used = u;
}	
	
double Candidate::calcMetric(double rtt, double d) {
	return 1000*rtt*(1 + d/7.5);
}
	
double Candidate::getMetric() const{
	return calcMetric(rtt,distance);
}
	
bool Candidate::operator< (const Candidate& p) const{
	return (getMetric() < p.getMetric());
}

bool Candidate::operator== (const Candidate& p) const{
	return (getMetric() == p.getMetric());
}

